package br.com.massai.model.dao.jdbc;

import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Singleton;
import javax.ejb.Startup;

import br.com.massai.model.exceptions.ErrorCore;
import br.com.massai.model.exceptions.SystemException;

import com.mchange.v2.c3p0.ComboPooledDataSource;

@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class ConnectionSingleton implements ConnectionPool {

	private static final long serialVersionUID = 5072726725706765792L;

	private static final int INITIAL_POOL_SIZE = 10;
	private static final int ACQUIRE_INCREMENT = 20;
	private static final int MAX_STATEMENTS = 20;
	private static final int MIN_POOL_SIZE = 5;
	private static final int MAX_POOL_SIZE = 30;

	private ComboPooledDataSource dataSourceSienge;
	private ComboPooledDataSource dataSourceFortes;
	private ComboPooledDataSource dataSourcePortal;

	private ConnectionSingleton() { }

	@SuppressWarnings("unused")
	@PostConstruct
	private void init() throws IOException, SQLException, SystemException {
		this.createPooledSienge();
		this.createPooledFortes();
	}

	@Override
	@Lock(LockType.READ)
	public Connection getConnection(ConnectionDB connectionDB) throws SQLException, IOException {
		try {
			switch (connectionDB) {
			case FORTES:
				this.createPooledFortes();
				return dataSourceFortes.getConnection();

			case SIENGE:
				this.createPooledSienge();
				return dataSourceSienge.getConnection();
				
			case PORTAL:
				this.createPooledPortal();
				return dataSourcePortal.getConnection();

			default:
				return null;
			}

		} catch (SQLException e) {
			e.printStackTrace();
			throw new SystemException(ErrorCore.ERROR_DATABASE_CONNECTION, e, connectionDB.name());
		}
	}

	@Lock(LockType.WRITE)
	private void createPooledSienge() throws SQLException, IOException {
		if(dataSourceSienge == null){
			try {
				ResourceBundle rb = ResourceBundle.getBundle("database");
				dataSourceSienge = new ComboPooledDataSource();
				dataSourceSienge.setInitialPoolSize(INITIAL_POOL_SIZE);
				dataSourceSienge.setAcquireIncrement(ACQUIRE_INCREMENT);
				dataSourceSienge.setMaxPoolSize(MAX_POOL_SIZE);
				dataSourceSienge.setMinPoolSize(MIN_POOL_SIZE);
				dataSourceSienge.setMaxStatements(MAX_STATEMENTS);
				
				dataSourceSienge.setJdbcUrl(rb.getString("db.sienge.url"));
				dataSourceSienge.setUser(rb.getString("db.sienge.username"));
				dataSourceSienge.setPassword(rb.getString("db.sienge.password"));
				dataSourceSienge.setDriverClass(rb.getString("db.sienge.jdbcDriver"));

			} catch (PropertyVetoException e) {
				e.printStackTrace();
				throw new SystemException(ErrorCore.ERROR_DATABASE_CONNECTION);
			}
		}
	}

	@Lock(LockType.WRITE)
	private void createPooledFortes() throws SQLException, IOException {
		if(dataSourceFortes == null){
			try {
				ResourceBundle rb = ResourceBundle.getBundle("database");
				dataSourceFortes = new ComboPooledDataSource();
				dataSourceFortes.setInitialPoolSize(INITIAL_POOL_SIZE);
				dataSourceFortes.setAcquireIncrement(ACQUIRE_INCREMENT);
				dataSourceFortes.setMaxPoolSize(MAX_POOL_SIZE);
				dataSourceFortes.setMinPoolSize(MIN_POOL_SIZE);
				dataSourceFortes.setMaxStatements(MAX_STATEMENTS);
				
				dataSourceFortes.setJdbcUrl(rb.getString("db.fortes.url"));
				dataSourceFortes.setUser(rb.getString("db.fortes.username"));
				dataSourceFortes.setPassword(rb.getString("db.fortes.password"));
				dataSourceFortes.setDriverClass(rb.getString("db.fortes.jdbcDriver"));

			} catch (PropertyVetoException e) {
				e.printStackTrace();
				throw new SystemException(ErrorCore.ERROR_DATABASE_CONNECTION);
			}
		}
	}
	
	@Lock(LockType.WRITE)
	private void createPooledPortal() throws SQLException, IOException {
		if(dataSourcePortal == null){
			try {
				ResourceBundle rb = ResourceBundle.getBundle("database");
				dataSourcePortal = new ComboPooledDataSource();
				dataSourcePortal.setInitialPoolSize(INITIAL_POOL_SIZE);
				dataSourcePortal.setAcquireIncrement(ACQUIRE_INCREMENT);
				dataSourcePortal.setMaxPoolSize(MAX_POOL_SIZE);
				dataSourcePortal.setMinPoolSize(MIN_POOL_SIZE);
				dataSourcePortal.setMaxStatements(MAX_STATEMENTS);

				dataSourcePortal.setJdbcUrl(rb.getString("db.portal.url"));
				dataSourcePortal.setUser(rb.getString("db.portal.username"));
				dataSourcePortal.setPassword(rb.getString("db.portal.password"));
				dataSourcePortal.setDriverClass(rb.getString("db.portal.jdbcDriver"));

			} catch (PropertyVetoException e) {
				e.printStackTrace();
				throw new SystemException(ErrorCore.ERROR_DATABASE_CONNECTION);
			}
		}
	}
}